//
//  AppController.m
//  PicUploader
//
//  Created by Chen Zhang on 8/13/08.
//  Copyright 2008 overboming. All rights reserved.
//  
//

#import "AppController.h"
#import "PUTableView.h"
#import "PUPicture.h"
#import "PUBoard.h"
#import "ZCScraping.h"
#import "PreferenceController.h"

@implementation AppController

- (id) init
{
    self = [super init];
    if (self) {
        threadLock = [[NSLock alloc] init];
		pictures = [[NSMutableArray alloc] init];
        // Add your subclass-specific initialization here.
        // If an error occurs here, send a [self release] message and return nil.    
        uploadCounter = 1;
        uploadString = [[NSString alloc] initWithString:@""];
        maxThreadNum = 2;
        whetherStarted = 0; //not started
        imageQuality = @"High";  //default high image quality
        imageSize = @"Original";
        
        //register notification
        NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
        [nc addObserver:self
               selector:@selector(handleFavBoardChange:)
                   name:ZCFavBoardChangedNotification
                 object:nil];
        [nc addObserver:self
               selector:@selector(handleThreadNumChange:)
                   name:ZCThreadNumChangedNotification
                 object:nil];
        [nc addObserver:self
               selector:@selector(handleBoardListChange:)
                   name:ZCBoardListChangedNotification
                 object:nil];
        [nc addObserver:self
               selector:@selector(handleImageQualityChange:)
                   name:ZCImageQualityChangedNotification
                 object:nil];
        [nc addObserver:self
               selector:@selector(handleImageSizeChange:)
                   name:ZCImageSizeChangedNotification
                 object:nil];
                
        
        //we have to clear the Cache directory
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        NSAssert([paths count] > 0, @"~/Library/Caches");
        sCacheDir = [[[paths objectAtIndex:0] stringByAppendingPathComponent:@"AttachBot"] retain];
                
    }
    return self;
}

#pragma mark -
#pragma mark Sheet Handlers

- (void)openPanelDidEnd:(NSOpenPanel *)openPanel
             returnCode:(int)returnCode
            contextInfo:(void *)x
{
    
    // Did they choose "Open"?
    if (returnCode == NSOKButton) {
        NSArray *pathArray = [openPanel filenames];
        for (NSString *path in pathArray){
          //  //NSLog(path);
            NSFileManager *fileManager = [NSFileManager defaultManager];
            NSDictionary *fileAttributes = [fileManager fileAttributesAtPath:path traverseLink:YES];
            NSNumber *fileSize;
            NSString *fileName;
            
            if (fileAttributes != nil) {
                if (fileSize = [fileAttributes objectForKey:NSFileSize]) {
				}
                if (fileName = [[NSString alloc] initWithString:path]){
                    ;
                }
                //can get more attributes;
            }    
            int fz = [fileSize intValue] / 1024;  //got fileSize by K
            NSString *defaultComment = [[NSString alloc] initWithString:@""];
            NSMutableAttributedString *defaultStatus;
            if(fz < 1010)
                defaultStatus = [[NSMutableAttributedString alloc]
                                 initWithString:@"Ready"];
            else{
                defaultStatus = [[NSMutableAttributedString alloc]
                     initWithString:@"TOO BIG"];
                [defaultStatus addAttribute:NSForegroundColorAttributeName
                          value:[NSColor redColor]
                                      range:NSMakeRange(0, 7)];
            }
            
            PUPicture *mypic = [[PUPicture alloc] initWithPath:fileName Size:fz Status:defaultStatus Comment:defaultComment];
            
            [picturesController addObject:mypic];
            [picturesController rearrangeObjects];
            [tableView reloadData];
        }
        
        validPicNum = [self countValidPicture];
        [dockTile setBadgeLabel:[NSString stringWithFormat:@"%d",validPicNum]];
           
        //auto convert the images that are too large~~~
        [progress startAnimation:nil];
        [statusBar setStringValue:@"Converting images..."];
        
        for(PUPicture *pic in pictures){
            NSString *newpath = [[pic filePath] retain];
            NSFileManager *fileManager = [NSFileManager defaultManager];
            NSDictionary *fileAttributes = [fileManager fileAttributesAtPath:newpath traverseLink:YES];
            NSNumber *fileSize;        
            if (fileAttributes != nil) {
                if (fileSize = [fileAttributes objectForKey:NSFileSize]) {
				}
            }    
            int fz = [fileSize intValue] / 1024;  //got fileSize by K
            if(fz >= 1024 && ( [[newpath uppercaseString]  hasSuffix:@".BMP"] || 
                               [[newpath uppercaseString] hasSuffix:@".PNG"] ||
							  [[newpath uppercaseString] hasSuffix:@".TIF"] ||
							  [[newpath uppercaseString] hasSuffix:@".TIFF"]

               )){ 
                //convert always if user click convert button manually
                //we convert these images
                NSString *cachePath = [[self handleLargeFile:newpath ImageQuality:@"High"] retain];
                [pic setFilePath:cachePath];
                int newSize = [self checkFileSize:cachePath];
                [pic setFileSize:newSize];
                [tableView reloadData];
                if(newSize < 1024){
                    //set it ready
                    [pic setPicStatus: [[[NSMutableAttributedString alloc]
                                         initWithString:@"Ready"] retain]];
				}
            }
        }
        [statusBar setStringValue:@""];
        [progress stopAnimation:nil];
        
    } 
}

- (IBAction)showOpenPanel:(id)sender
{
    NSOpenPanel *panel = [NSOpenPanel openPanel];
    [panel setAllowsMultipleSelection:true];
    // Run the open panel
    [panel beginSheetForDirectory:nil
                             file:nil
                            types:[NSImage imageFileTypes]
                   modalForWindow:[tabView window]
                    modalDelegate:self
                   didEndSelector:
     @selector(openPanelDidEnd:returnCode:contextInfo:)
                      contextInfo:NULL];
}

- (IBAction)showLoginSheet:(id)sender
{
    [userNameText setStringValue:[scrapeManager userid]];
    [passwordText setStringValue:[scrapeManager password]];
    [NSApp beginSheet:loginSheet
       modalForWindow:[tabView window]
        modalDelegate:nil
       didEndSelector:NULL
          contextInfo:NULL];
    
}
- (IBAction)endLoginSheet:(id)sender
{
    [NSApp endSheet:loginSheet];
    [loginSheet orderOut:sender];
    NSString *username = [userNameText stringValue];
    NSString *password = [passwordText stringValue];
    [scrapeManager release]; //release previous one
    scrapeManager = [[ZCScraping alloc] initWithUserName:username Password:password Controller:self];
    [[[PreferenceController alloc] init] updateAccountInfo:self];
}

- (IBAction)dismissLoginSheet:(id)sender
{
    [NSApp endSheet:loginSheet];
    [loginSheet orderOut:sender];
}

- (IBAction)showSuggestionPanel:(id)sender
{
    [NSApp beginSheet:suggestSheet
       modalForWindow:[tabView window]
        modalDelegate:nil
       didEndSelector:NULL
          contextInfo:NULL];
    
}
- (IBAction)endSuggestionSheet:(id)sender
{
    [NSApp endSheet:suggestSheet];
    [suggestSheet orderOut:sender];
}

- (IBAction)showAboutMePanel:(id)sender
{
    if(aboutMePanel != nil)
        [aboutMePanel makeKeyAndOrderFront:nil];
}

#pragma mark -
#pragma mark Event Handlers

- (IBAction)uploadAll:(id)sender
{

    if([self countValidPicture] <= 0 || whetherStarted > 0)
        return;
    whetherStarted = 1; //start
    [switchMenu setEnabled:NO];
    
    [progress startAnimation:nil];

        
    
    //make sure I am online
    [statusBar setStringValue:@"Detecting logging info..."];
    if(![scrapeManager detectLoggedIn]){
        
        if(whetherStarted == 0)
            return;
        [statusBar setStringValue:@"Logging in..."];
        [scrapeManager Login];
        
        if(whetherStarted == 0) {
            //failed connection shouldn't connect
            [statusBar setStringValue:@"Log in failed"];
            return;
        }
        [statusBar setStringValue:@"Log in complete."];
    
        //save cookie once relogin
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        NSString *cookiestr = [[scrapeManager cookiestring] retain];
        NSData *cookiestrAsData = 
        [NSKeyedArchiver archivedDataWithRootObject:cookiestr];
        [defaults setObject:cookiestrAsData forKey:ZCCookieStringKey];
    }
    else
        //NSLog(@"I was logged in");
    
    [statusBar setStringValue:@"Starting Workload..."];
    validPicNum = [self countValidPicture];
    //only count before uploading and trust the number
    
    
    if(validPicNum <= maxThreadNum){
        
    for(PUPicture *pic in pictures){
        if(![[[pic picStatus] mutableString] isEqualToString:@"Ready"]){
            continue; //do nothing for something not ready
        }
        //NSLog(@"picture: %@",[pic filePath]);
        [pic setPicStatus:[[NSMutableAttributedString alloc]
                           initWithString:@"Uploading"]];
        [tableView reloadData];            
      //first set up as many as thread as possible 
        [NSThread detachNewThreadSelector:@selector(UploadThreadDelegate:) toTarget:self withObject:[pic filePath]]; 
    }
        currentDoneNum += validPicNum;
    } //we could finish with first rush
    else
    {
        currentDoneNum += maxThreadNum;
        //NSLog(@"I have uploaded %d pics",currentDoneNum);
        
        //start maxThreadNum valid threads and wait for call back
        int valid = 0;
        int i = 0;
        for(;valid < maxThreadNum;i++){
            PUPicture *pic = [pictures objectAtIndex:i];
            if(![[[pic picStatus] mutableString] isEqualToString:@"Ready"]){
                //NSLog(@"Not Ready for this pic");
                continue; //do nothing for something not ready
            }
            //NSLog(@"picture: %@",[pic filePath]);
            [pic setPicStatus:[[NSMutableAttributedString alloc]
                               initWithString:@"Uploading"]];
            [tableView reloadData];            
            [NSThread detachNewThreadSelector:@selector(UploadThreadDelegate:) toTarget:self withObject:[pic filePath]];  
            valid++;
        }
        nextComePicNum = i; //it's to come, but you can still meet invalid ones
      //  //NSLog(@"I will upload %d as the next",nextComePicNum);

    }
    
}

- (void)endCurrentTask
{
    whetherStarted = 0; 
    [progress stopAnimation:nil];
    [statusBar setStringValue:@"Failed"];
}


- (void) UploadThreadDelegate:(id)path
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    [scrapeManager UploadThreadBranch:path];
    //check if I have done enough?
    //whether fire up new thread to complete
    [threadLock lock];    
    if(validPicNum > currentDoneNum){
        //attach
        //NSLog(@"I am trying to attach a new thread");
        currentDoneNum ++;
        
        PUPicture *pic = [pictures objectAtIndex:nextComePicNum];
        while(![[[pic picStatus] mutableString] isEqualToString:@"Ready"]){
            pic = [pictures objectAtIndex:++nextComePicNum];
        }
        [self performSelectorOnMainThread:@selector(fireupNewThread:) withObject:[NSNumber numberWithInt:nextComePicNum] waitUntilDone:NO];
        //NSLog(@"new thread attached done");
        nextComePicNum++;
        [threadLock unlock];
    }
    else
        [threadLock unlock];
    [pool release];
}

- (int) countValidPicture
{
    int i = 0;
    for(PUPicture *pic in pictures){
        if([[[pic picStatus] mutableString] isEqualToString:@"Ready"]
             || [[[pic picStatus] mutableString] isEqualToString:@"Done"]
            || [[[pic picStatus] mutableString] isEqualToString:@"Uploading"]
            || [[[pic picStatus] mutableString] isEqualToString:@"Failed"]
            )
            i++;
    }
    return i;
}


- (IBAction)cancelAndQuit:(id)sender
{
    [NSApp endSheet:loginSheet];
    [loginSheet orderOut:sender];
    [NSApp terminate:sender];
}


- (void) dealloc
{
    [pictures release];
    NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
    [nc removeObserver:self];
    [super dealloc];
}


//maintain a Max num of thread therehold
//if one dies and there is more pic, start a new thread to deal with it
//until the uploadCounter reaches the pictures counter;
- (void) uploadCompleteForOneThread:(NSString *)filename Path:(NSString *)filepath
{
    
    PUPicture *donePic = [[self findPictureByFilePath:filepath] retain];
    NSString *helper = [[NSString alloc] initWithFormat:@"%@\n%@\n",filename,[donePic picComment]];
    [donePic setUploadString:helper];
    
    [threadLock lock]; //critical stage
    
    [statusBar setStringValue:[NSString stringWithFormat:@"Picture %d is uploaded",uploadCounter]];
    [donePic setPicStatus:[[NSMutableAttributedString alloc]
                           initWithString:@"Done"]];
    [tableView reloadData];
    [donePic release];
    [threadLock unlock]; 
    
    [threadLock lock]; //critical stage
    
    validPicNum = [self countValidPicture];
    [dockTile setBadgeLabel:[NSString stringWithFormat:@"%d",validPicNum - uploadCounter]];
    
    //check if it's done uploading!!!
    if(uploadCounter == validPicNum){
        //if done 
        //NSLog(@"wohahahaha");
        //NSLog(@"lol");  
        [progress stopAnimation:nil];
        [uploadContent insertText:@""];
        for(PUPicture *pic in pictures){
            [uploadContent insertText:[pic uploadString]];
        }
        [uploadContent insertText:@"\n"];
        [statusBar setStringValue:@"Upload complete"];
        [boardNameBoxForPost setStringValue:[boardNameBox stringValue]];
        [tabView selectTabViewItemAtIndex:1];
        [titleField selectText:self];
        uploadCounter = 1; // reset counter
        validPicNum = 0; //reset
        nextComePicNum = 0; 
        currentDoneNum = 0;
        whetherStarted = 0;
        [picturesController removeObjects:pictures];//ready for next upload
        [tableView reloadData];
        [threadLock unlock]; 
        [switchMenu setEnabled:YES];
        
        validPicNum = [self countValidPicture];
        [dockTile setBadgeLabel:[NSString stringWithFormat:@"%d",validPicNum]];
        
        //notifiy user, we are finished!
        NSAlert *alert = [NSAlert alertWithMessageText:@"Complete! "
                                         defaultButton:@"OK"
                                       alternateButton:nil
                                           otherButton:nil
                             informativeTextWithFormat:@"Links to your attachments have been sent to your clipboard. %@",@""];
        [alert runModal];
        //after running model, send the string with in the container to the pasteboard
        [[NSPasteboard generalPasteboard] declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
        [[NSPasteboard generalPasteboard] setString:[[uploadContent textStorage] mutableString] forType:NSStringPboardType];
        return;
    }
    uploadCounter ++;
    [threadLock unlock]; 
    //done with previous pic~~    
}

- (PUPicture *) findPictureByFilePath:(NSString *)filepath
{
    for(PUPicture *pic in pictures){
        if([[pic filePath] isEqualToString:filepath]){
            [pic autorelease];
            return pic;
        }
    }
    return nil;
}


- (void)applicationWillTerminate:(NSNotification *)aNotification
{    
    //and when uploadall is invoked, it will first try the stored cookie to 
    //see if it's still valid, by which way I am gonna avoid the 
    //constantly login error.
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    if(![scrapeManager cookiestring]){
        NSString *cookiestr = [[scrapeManager cookiestring] retain];
        NSData *cookiestrAsData = 
        [NSKeyedArchiver archivedDataWithRootObject:cookiestr];
        [defaults setObject:cookiestrAsData forKey:ZCCookieStringKey];
    }

    // clean it at exit
    BOOL flag = NO;
    int pid = [[NSProcessInfo processInfo] processIdentifier];
    // detect if another AttachBot exists
    for (NSDictionary *dict in [[NSWorkspace sharedWorkspace] launchedApplications]) {
        if ([[dict objectForKey:@"NSApplicationName"] isEqual:@"AttachBot"] &&
            [[dict objectForKey:@"NSApplicationProcessIdentifier"] intValue] != pid) {
            flag = YES;
            break;
        }
    }
    // no other AttachBot,clear the cache directory
    if (!flag)
        [[NSFileManager defaultManager] removeFileAtPath:sCacheDir handler:nil];
	
	// Signout? I guess, it's time
	[scrapeManager Logout];
}

- (void) firstLoginThread:(id)object
{
    //I will hesitate for 0.5 second, then, start the sheet 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    [NSThread sleepForTimeInterval:0.5];
    [self showLoginSheet:switchUserMenu];
    [pool release];
}


- (void)awakeFromNib
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *usernameAsData = [defaults objectForKey:ZCFavUserNameKey];
    NSString* username =  [NSKeyedUnarchiver unarchiveObjectWithData:usernameAsData];
    
    NSData *passwordAsData = [defaults objectForKey:ZCFavPasswordKey];
    NSString *password = [NSKeyedUnarchiver unarchiveObjectWithData:passwordAsData];
    //NSLog(@"starting up ScrapeManager");
    
    NSData *cookiestringAsData = [defaults objectForKey:ZCCookieStringKey];
    NSString *cookiestr = [NSKeyedUnarchiver unarchiveObjectWithData:cookiestringAsData];
    
    NSData *favBoardNameAsData = [defaults objectForKey:ZCFavBoardKey];
    NSString *boardNamestr = [NSKeyedUnarchiver unarchiveObjectWithData:favBoardNameAsData];
    
    NSData *imageQualityAsData = [defaults objectForKey:ZCImageQualityKey];
    NSString *imageQualitytemp = [NSKeyedUnarchiver unarchiveObjectWithData:imageQualityAsData];
    
    NSData *imageSizeAsData = [defaults objectForKey:ZCImageSizeKey];
    NSString *imageSizetemp = [NSKeyedUnarchiver unarchiveObjectWithData:imageSizeAsData];
    
    [boardNameBox setStringValue:boardNamestr];
    [boardNameBoxForPost setStringValue:boardNamestr];
    currentBoardName = boardNamestr;
    imageQuality = [imageQualitytemp retain];
    imageSize = [imageSizetemp retain];
    [tableView setRowHeight:60];
    
    maxThreadNum = [defaults integerForKey:ZCMaxThreadNumKey];
    
    NSData *boardNameListAsData = [defaults objectForKey:ZCBoardNameList];
    listOfBoardName = [[NSKeyedUnarchiver unarchiveObjectWithData:boardNameListAsData] retain];
    
    //NSLog(@"set max thread num %d",maxThreadNum);
    
    if([username isEqualToString:@""] || [password isEqualToString:@""]){
        //first run, or no username is available
        [NSThread detachNewThreadSelector:@selector(firstLoginThread:) toTarget:self withObject:nil]; 
    }
    
    scrapeManager = [[ZCScraping alloc] initWithUserName:username Password:password Controller:self];
    //prevent login in too frequently by opening and closing applications 
    [scrapeManager setCookiestring:cookiestr]; //no memory leak, handled by objc2.0
        
    //set double click action
	//NEW, disabled for snow leopard
//    [tableView setDoubleAction:@selector(previewSelectedItems:)];

    // get our Dock tile to this app
	dockTile = [NSApp dockTile];	
    [dockTile setBadgeLabel:@"0"];
 
	SInt32 ver;
	if (Gestalt(gestaltSystemVersion, &ver) == noErr && ver < 0x1060) {
		[qlButton setEnabled:YES];
	}
}



#pragma mark -
#pragma mark - Data Source

- (id)comboBox:(NSComboBox *)aComboBox objectValueForItemAtIndex:(NSInteger)index
{        
    return [[listOfBoardName objectAtIndex:index] boardName];
}

- (NSInteger)numberOfItemsInComboBox:(NSComboBox *)aComboBox
{
        //NSLog(@"%d",[listOfBoardName count]);
        return [listOfBoardName count];
}

#pragma mark -
#pragma mark Drag and Drop Handlers

- (void) acceptDragOperation:(NSString *)path
{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSDictionary *fileAttributes = [fileManager fileAttributesAtPath:path traverseLink:YES];
    NSNumber *fileSize;
    NSString *fileName;
    
    if (fileAttributes != nil) {
        //NSLog(@"%@",fileAttributes);
        if (fileSize = [fileAttributes objectForKey:NSFileSize]) {
            //NSLog(@"File size: %qi\n", [fileSize unsignedLongLongValue]);
        }
        if (fileName = [[NSString alloc] initWithString:path]){
            if(![self acceptFileName:fileName]){
                return;  //do not accept this one
            }
        }
        //can get more attributes;
    }    
    int fz = [fileSize intValue] / 1024;  //got fileSize by K
    NSString *defaultComment = [[NSString alloc] initWithString:@""];
    NSMutableAttributedString *defaultStatus;
    if(fz < 1010)
        defaultStatus = [[NSMutableAttributedString alloc]
                         initWithString:@"Ready"];
    else{
        defaultStatus = [[NSMutableAttributedString alloc]
                         initWithString:@"TOO BIG"];
        [defaultStatus addAttribute:NSForegroundColorAttributeName
                              value:[NSColor redColor]
                              range:NSMakeRange(0, 7)];
    }
    PUPicture *pic = [[PUPicture alloc] initWithPath:fileName Size:fz Status:defaultStatus Comment:defaultComment];
	
    NSString *newpath = [[pic filePath] retain];
    
    if (fileAttributes != nil) {
        if (fileSize = [fileAttributes objectForKey:NSFileSize]) {
            //NSLog(@"File size: %qi\n", [fileSize unsignedLongLongValue]);
        }
    }    
    if(fz >= 1024 && ([[newpath uppercaseString] hasSuffix:@".BMP"] || 
                      [[newpath uppercaseString] hasSuffix:@".PNG"] ||
                      [[newpath uppercaseString] hasSuffix:@".TIF"]
                      )){ 
        //convert always if user click convert button manually
        //we convert these images
        NSString *cachePath = [[self handleLargeFile:newpath ImageQuality:@"High"] retain];
        [pic setFilePath:cachePath];
        int newSize = [self checkFileSize:cachePath];
        [pic setFileSize:newSize];
        [tableView reloadData];
        if(newSize < 1024){
            //set it ready
            [pic setPicStatus: [[[NSMutableAttributedString alloc]
                                 initWithString:@"Ready"] retain]];
            
        }
    }
    

    [picturesController addObject:pic];
    [picturesController rearrangeObjects];
    [tableView reloadData];            
    validPicNum = [self countValidPicture];
    [dockTile setBadgeLabel:[NSString stringWithFormat:@"%d",validPicNum]];
}

/*
 * save data to a file and use acceptDragOperation
 */
- (void) acceptDragOperationForDraggedImage:(NSData *)data
{
    //NSLog(@"image dragged size %d", [data length]);
    [[NSFileManager defaultManager] createDirectoryAtPath:sCacheDir attributes:nil];
    double time = [[NSDate date] timeIntervalSince1970];
    //writing to a TIFF picture
    NSString *_path = [[sCacheDir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.TIFF",[NSString stringWithFormat:@"%lf",time]]] retain];
    [data writeToFile:_path atomically:YES]; //write to cache directory with proper name
    
    NSString *newpath = [self handleLargeFile:_path ImageQuality:@"High"];
    [self acceptDragOperation:newpath];
    [_path release];
}



#pragma mark -

- (BOOL) acceptFileName:(NSString *)filename
{
	NSLog(@"%@",[filename uppercaseString]);
    if([[filename uppercaseString] hasSuffix:@".PNG"])
        return YES;
    if([[filename uppercaseString] hasSuffix:@".JPG"])
        return YES;
    if([[filename uppercaseString] hasSuffix:@".BMP"])
        return YES;
    if([[filename uppercaseString] hasSuffix:@".JPEG"])
        return YES;
    if([[filename uppercaseString] hasSuffix:@".PDF"])
        return YES;
    if([[filename uppercaseString] hasSuffix:@"TIF"])
        return YES;
    return NO;
}

- (IBAction)showPreferencePanel:(id)sender
{
    // Is preferenceController nil?
    if (!preferenceController) {
        preferenceController = [[PreferenceController alloc] init];
    }
    [[PreferenceController sharedPrefsWindowController] showWindow:nil];
	(void)sender;
}

- (IBAction)previewSelectedItems:(id)sender
{
    NSArray *selectedPics = [picturesController selectedObjects];
    if([selectedPics count] <= 0)
        return;
    [progress startAnimation:nil];    
//    [WLQuickLookBridge removeAll];

    for(PUPicture *pic in selectedPics){
        [WLQuickLookBridge add:[NSURL fileURLWithPath:[pic filePath]]];
    }
    [WLQuickLookBridge orderFront];
    if(!whetherStarted)
        [progress stopAnimation:nil];
        
}

- (IBAction)postMyArticle:(id)sender
{
 //give visual to user
    //Attach a new thread
    if([[[uploadContent textStorage] mutableString] isEqualToString:@""])
        return;
    [NSThread detachNewThreadSelector:@selector(postMyArticleThread:) toTarget:self withObject:nil];
}

- (IBAction)postMySuggestion:(id)sender
{
    if([[[sugguestionTextView textStorage] mutableString] isEqualToString:@""])
        return;
    [self endSuggestionSheet:self];
    //Attach a new thread
    [NSThread detachNewThreadSelector:@selector(postMySuggestionThread:) toTarget:self withObject:nil];
}

- (void)postMyArticleThread:(id)object
{
    NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
    whetherStarted = 1;
    [postProgress startAnimation:nil];
    //make sure I am online
    if(![scrapeManager detectLoggedIn]){
        if(whetherStarted == 0){
            [postProgress stopAnimation:nil];
            return;
        }        
        [scrapeManager Login];
    }
    NSString *post = [[NSString alloc] initWithFormat:
                      @"%@=%d&%@=%@&%@=%@&%@=%@&%@=%@&%@=%@",
                      @"replymode",2,
                      @"id", @"", //default blank1
                      @"gid", @"",   //default blank
                      @"title",[titleField stringValue],
                      @"signature",[sigComboBox stringValue],
                      @"text",[NSString stringWithFormat:@"%%0D%%0A%@",[[uploadContent textStorage] mutableString]]];
    NSString *response = [scrapeManager PostArticle:[boardNameBoxForPost stringValue] withData:post];
    NSString *message;
    if([response rangeOfString:@"发表成功"].location != NSNotFound){
        message = @"Your Post is There !\n Check it out!";
    }
    else
        message = @"Oops! Something wrong has happened.";
    
    NSAlert *alert = [NSAlert alertWithMessageText:@"Attention" defaultButton:@"dismiss" alternateButton:nil otherButton:nil informativeTextWithFormat:message];
    [response release];
    [post release];
    [postProgress stopAnimation:nil];
    [alert runModal];
    [loopPool release];
    whetherStarted = 0; //job done
}
- (void)postMySuggestionThread:(id)object
{
    NSAutoreleasePool *loopPool = [[NSAutoreleasePool alloc] init];
   
    whetherStarted = 1;
    //make sure I am online
    [postProgress startAnimation:nil];
    if(![scrapeManager detectLoggedIn]){
        if(whetherStarted == 0){
            [postProgress stopAnimation:nil];
            return;
        }
        [scrapeManager Login];
    }

    NSString *post = [[NSString alloc] initWithFormat:
                      @"%@=%@&%@=%@&%@=%d&%@=%@&%@=%@",
                      @"title",[NSString stringWithFormat:@"[AttachBot] Suggestion coming form %@", [scrapeManager userid]],
                      @"userid",@"overboming",  //sending to the author
                      @"signiture",[sigSComboBox stringValue],
                      @"backup", @"on", //default on
                      @"text", [[sugguestionTextView textStorage] mutableString]];
    
    //NSLog(post);
    NSString *response = [scrapeManager PostSuggestion:post];
	
    NSString *message;
    if([response rangeOfString:@"信件已寄给"].location != NSNotFound){
        message = @"Your Sugguestion is sent to overboming!\n Thank you";
    }
    else
        message = @"Oops! Something wrong has happened.";
    
    NSAlert *alert = [NSAlert alertWithMessageText:@"Attention" defaultButton:@"dismiss" alternateButton:nil otherButton:nil informativeTextWithFormat:message];
    [response release];
    [post release];
    [postProgress stopAnimation:nil];
    [alert runModal];
    [loopPool release];
    whetherStarted = 0; //job done
}


- (void)fireupNewThread:(id)object
{
    //based on nextComePicNum,find a valid and stop
    //fire it.
    [threadLock lock];
    while(YES){  
        //NSLog(@"I am trying to read %d",[object intValue]);
        PUPicture *pic = [pictures objectAtIndex:[object intValue]];
        if(![[[pic picStatus] mutableString] isEqualToString:@"Ready"]){
            //NSLog(@"Not Ready for this pic");
            continue; //do nothing for something not ready
        }
        //NSLog(@"picture: %@",[pic filePath]);
        [pic setPicStatus:[[NSMutableAttributedString alloc]
                           initWithString:@"Uploading"]];
        [tableView reloadData];            
        [NSThread detachNewThreadSelector:@selector(UploadThreadDelegate:) toTarget:self withObject:[pic filePath]];  
        //job done
        break;
    }
    [threadLock unlock];
}

#pragma mark -
#pragma mark Notification Handlers

/*handle notification*/
- (void)handleFavBoardChange:(NSNotification *)note
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *favBoardAsData = [defaults objectForKey:ZCFavBoardKey];
    NSString *favBoard = [[NSKeyedUnarchiver unarchiveObjectWithData:favBoardAsData] retain];
    [boardNameBox setStringValue:favBoard];
    [boardNameBoxForPost setStringValue:favBoard];
    
}
- (void)handleThreadNumChange:(NSNotification *)note
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    maxThreadNum = [defaults integerForKey:ZCMaxThreadNumKey];
    
}
- (void)handleBoardListChange:(NSNotification *)note
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *boardNameListAsData = [defaults objectForKey:ZCBoardNameList];
    listOfBoardName = [[NSKeyedUnarchiver unarchiveObjectWithData:boardNameListAsData] retain];
}

- (void)handleImageQualityChange:(NSNotification *)note
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *imageQualityListAsData = [defaults objectForKey:ZCImageQualityKey];
    [imageQuality release];
    imageQuality = [[NSKeyedUnarchiver unarchiveObjectWithData:imageQualityListAsData] retain];  
    //NSLog(@"change to %@",imageQuality);
}

- (void)handleImageSizeChange:(NSNotification *)note
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    NSData *imageSizeAsData = [defaults objectForKey:ZCImageSizeKey];
    [imageSize release];
    imageSize = [[NSKeyedUnarchiver unarchiveObjectWithData:imageSizeAsData] retain];  
    //NSLog(@"change to %@",imageSize);
}



#pragma mark -
- (IBAction) convertToSmallerSize:(id)sender
{
    NSArray *selectedPics = [picturesController selectedObjects];
    if([selectedPics count] <= 0)
        return;
    [progress startAnimation:nil];    
    
    for(PUPicture *pic in selectedPics){
        NSString *newpath = [[pic filePath] retain];
        NSFileManager *fileManager = [NSFileManager defaultManager];
        NSDictionary *fileAttributes = [fileManager fileAttributesAtPath:newpath traverseLink:YES];
        NSNumber *fileSize;        
        if (fileAttributes != nil) {
            if (fileSize = [fileAttributes objectForKey:NSFileSize]) {
                //NSLog(@"File size: %qi\n", [fileSize unsignedLongLongValue]);
            }
        }    
        int fz = [fileSize intValue] / 1024;  //got fileSize by K
        if(fz >= 1024 && ([newpath hasSuffix:@".bmp"] || [newpath hasSuffix:@".BMP"] || 
                                    [newpath hasSuffix:@".png"] || [newpath hasSuffix:@".PNG"]) || YES){ 
            //convert always if user click convert button manually
            //we convert these images
            //NSString *cachePath = [[self handleLargeFile:newpath ImageQuality:imageQuality] retain];
            NSString *cachePath = [[self handleLargeFile:newpath ImageQuality:imageQuality toSize:imageSize] retain];
            [pic setFilePath:cachePath];
            int newSize = [self checkFileSize:cachePath];
            [pic setFileSize:newSize];
            [tableView reloadData];
            if(newSize < 1024){
                //set it ready
                [pic setPicStatus: [[[NSMutableAttributedString alloc]
                                    initWithString:@"Ready"] retain]];
                //get it ready
                //NSLog(@"it's ready at %@ with size %d",cachePath,newSize);
            }
        }
    }
    [progress stopAnimation:nil];
    validPicNum = [self countValidPicture];
    [dockTile setBadgeLabel:[NSString stringWithFormat:@"%d",validPicNum]];
    //NSLog(@"valid Pic Num %d",validPicNum);
}

- (IBAction) rotateTo90Degrees:(id)sender
{
    NSArray *selectedPics = [picturesController selectedObjects];
    if([selectedPics count] <= 0)
        return;
    [progress startAnimation:nil];    
    
    for(PUPicture *pic in selectedPics){
        NSString *cachePath = [self rotatePicture:[pic filePath]];
        [pic setFilePath:cachePath];
        //NSLog(@"new path: %@",cachePath); 
    }        
    [progress stopAnimation:nil];
    validPicNum = [self countValidPicture];
    [dockTile setBadgeLabel:[NSString stringWithFormat:@"%d",validPicNum]];
    //NSLog(@"valid Pic Num %d",validPicNum);
}



- (int) checkFileSize:(NSString *)filePath
{
    NSFileManager *fileManager = [NSFileManager defaultManager];
    NSDictionary *fileAttributes = [fileManager fileAttributesAtPath:filePath traverseLink:YES];
    NSNumber *fileSize;        
    if (fileAttributes != nil) {
        if (fileSize = [fileAttributes objectForKey:NSFileSize]) {
            //NSLog(@"File size: %qi\n", [fileSize unsignedLongLongValue]);
        }
    }    
    int fz = [fileSize intValue] / 1024;  //got fileSize by K
    return fz;
}

/*
 */
- (NSString *)handleLargeFile:(NSString *)filePath ImageQuality:(NSString *)str;
{
    NSImage *bigImage = [[NSImage alloc] initWithContentsOfFile:filePath];
    NSString *strstr = [str retain];
    //NSLog(@"we receieve this quaility",strstr);
    //after resizing, convertToJPG
    NSArray *representations;
    NSData *bitmapData;
    float quality = 0.98;
    representations = [bigImage representations];
    if([strstr isEqualToString:@"High"])
        quality = 0.98;
    else if([strstr isEqualToString:@"Medium"])
        quality = 0.9;
    else
        quality = 0.7;
    bitmapData = [NSBitmapImageRep representationOfImageRepsInArray:representations 
                                                          usingType:NSJPEGFileType 
                                                         properties:[NSDictionary dictionaryWithObject:[NSDecimalNumber numberWithFloat:quality] 
                                                         forKey:NSImageCompressionFactor]];
    //NSLog(@"new size %d",[bitmapData length]);
    NSString *_path;
    
    //create the directory if needed
    [[NSFileManager defaultManager] createDirectoryAtPath:sCacheDir attributes:nil];
    if(![[scrapeManager getFileNameFromPath:filePath] hasSuffix:@".jpg"])
    _path = [[sCacheDir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.jpg",[scrapeManager getFileNameFromPath:filePath]]] retain];
    else
    _path = [[sCacheDir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@",[scrapeManager getFileNameFromPath:filePath]]] retain];

    [bitmapData writeToFile:_path atomically:YES];
    [bigImage release];
    [_path autorelease];
    return _path;
}

- (NSString *)rotatePicture:(NSString *)filePath
{
    NSImage *image = [[NSImage alloc] initWithContentsOfFile:filePath];
    NSSize osize = [image size];
    float fromWidth = osize.width;
    float fromHeight = osize.height; 
    NSSize newSize = NSMakeSize(fromHeight,fromWidth);
    
    //NSLog(@"%f %f",fromWidth,fromHeight);
    
    NSImage *rotatedImage = [[NSImage alloc] initWithSize:newSize];
    [rotatedImage lockFocus];
    
    /**
     * Apply the following transformations:
     *
     * - bring the rotation point to the centre of the image instead of
     *   the default lower, left corner (0,0).
     * - rotate it by 90 degrees, either clock or counter clockwise.
     * - re-translate the rotated image back down to the lower left corner
     *   so that it appears in the right place.
     */
    NSAffineTransform *rotateTF = [NSAffineTransform transform];
    NSPoint centerPoint = NSMakePoint(newSize.width / 2, newSize.height / 2);
    
    BOOL clockwise = YES;
    
    [rotateTF translateXBy: centerPoint.x yBy: centerPoint.y];
    [rotateTF rotateByDegrees: (clockwise) ? - 90 : 90];
    [rotateTF translateXBy: -centerPoint.y yBy: -centerPoint.x];
    [rotateTF concat];
    
    /**
     * We have to get the image representation to do its drawing directly,
     * because otherwise the stupid NSImage DPI thingie bites us in the butt
     * again.
     */
    NSRect r1 = NSMakeRect(0, 0, newSize.height, newSize.width);
    [[image bestRepresentationForDevice: nil] drawInRect: r1];
    
    [rotatedImage unlockFocus];

    //NSLog(@"rotation done");

    NSData *bitmapData = [rotatedImage TIFFRepresentationUsingCompression: NSTIFFCompressionJPEG  factor:1.0];
    
    [rotatedImage release];
    rotatedImage = [[NSImage alloc] initWithData:bitmapData];

    NSString *_path;
    
    [[NSFileManager defaultManager] createDirectoryAtPath:sCacheDir attributes:nil];
    if(![[scrapeManager getFileNameFromPath:filePath] hasSuffix:@".jpg"])
        _path = [[sCacheDir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.jpg",[scrapeManager getFileNameFromPath:filePath]]] retain];
    else
        _path = [[sCacheDir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@",[scrapeManager getFileNameFromPath:filePath]]] retain];
    
    NSArray *representations;
    representations = [rotatedImage representations];
    NSData *imageData = [NSBitmapImageRep representationOfImageRepsInArray:representations 
                                                              usingType:NSJPEGFileType 
                                                             properties:[NSDictionary dictionaryWithObject:[NSDecimalNumber numberWithFloat:0.98] 
                                                                                                    forKey:NSImageCompressionFactor]];
    
    [imageData writeToFile:_path atomically:YES];
    return _path;
}


/*
 *control both quality or size of image
 */
- (NSString *)handleLargeFile:(NSString *)filePath ImageQuality:(NSString *)str toSize:(NSString *)sizestr
{
    NSImage *bigImage = [[NSImage alloc] initWithContentsOfFile:filePath];
    //we will try to reduce the bigImage to a smaller size, then control compression 
    NSSize osize = [bigImage size];
    float fromWidth = osize.width;
    float fromHeight = osize.height;
    float toWidth;
    float toHeight;
    if([sizestr isEqualToString:@"640"]){
        toWidth = 640;
        toHeight = fromHeight * (toWidth / fromWidth);
    }
    else if([sizestr isEqualToString:@"800"]){
        toWidth = 800;
        toHeight = fromHeight * (toWidth / fromWidth); 
    }
    else if([sizestr isEqualToString:@"1024"]){
        toWidth = 1024;
        toHeight = fromHeight * (toWidth / fromWidth);
    }
    else if([sizestr isEqualToString:@"1600"]){
        toWidth = 1600;
        toHeight = fromHeight * (toWidth / fromWidth);
    }
    else if([sizestr isEqualToString:@"Original"]){
        toWidth = fromWidth;
        toHeight = fromHeight;
    }
    
    NSImage *resizedImage = [[NSImage alloc] initWithSize: NSMakeSize(toWidth,toHeight)];
    [resizedImage lockFocus];
    [bigImage drawInRect: NSMakeRect(0, 0, toWidth, toHeight) fromRect: NSMakeRect(0, 0, fromWidth, fromHeight) operation: NSCompositeSourceOver fraction: 1.0];
    [resizedImage unlockFocus];
    [bigImage release];
    bigImage = resizedImage;
    //NSLog(@"new size !!! %f %f", [bigImage size].width,[bigImage size].height);
    
    //bigImage is now resized
   
    NSString *strstr = [str retain];
     float quality = 0.98;
    if([strstr isEqualToString:@"High"])
        quality = 0.98;
    else if([strstr isEqualToString:@"Medium"])
        quality = 0.9;
    else
        quality = 0.7;

    NSString *_path;
    NSData *bitmapData = [bigImage TIFFRepresentationUsingCompression: NSTIFFCompressionJPEG  factor:1.0];
    //bitmapData is NSData of tiff image with correct size
    
    
    NSImage *smallImage = [[NSImage alloc] initWithData:bitmapData];
    NSArray *representations;
    NSData *smallImageData;
    representations = [smallImage representations];
    smallImageData = [NSBitmapImageRep representationOfImageRepsInArray:representations 
                                                          usingType:NSJPEGFileType 
                                                         properties:[NSDictionary dictionaryWithObject:[NSDecimalNumber numberWithFloat:quality] 
                                                                                                forKey:NSImageCompressionFactor]];
    //create the directory if needed
    [[NSFileManager defaultManager] createDirectoryAtPath:sCacheDir attributes:nil];
    if(![[scrapeManager getFileNameFromPath:filePath] hasSuffix:@".jpg"])
        _path = [[sCacheDir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.jpg",[scrapeManager getFileNameFromPath:filePath]]] retain];
    else
        _path = [[sCacheDir stringByAppendingPathComponent:[NSString stringWithFormat:@"%@",[scrapeManager getFileNameFromPath:filePath]]] retain];
    
    [smallImageData writeToFile:_path atomically:YES];
    [bigImage release];
    [_path autorelease];
    return _path;
    
}

- (IBAction)removeFromArrayController:(id)sender
{
    NSArray *selectedPics = [picturesController selectedObjects];
    for(PUPicture *pic in selectedPics){
        [picturesController removeObject:pic];
    }
    validPicNum = [self countValidPicture];
    [dockTile setBadgeLabel:[NSString stringWithFormat:@"%d",validPicNum]];
}





@synthesize statusTextBar;
@synthesize scrapeManager;
@synthesize uploadString;
@synthesize boardNameBox;
@synthesize progress;
@synthesize statusBar;
@synthesize nextComePicNum;
@synthesize maxThreadNum;
@synthesize currentDoneNum;
@synthesize currentBoardName;
@end
